package tools.jackson.databind.node;

import org.junit.jupiter.api.Test;

import tools.jackson.databind.ObjectMapper;
import tools.jackson.databind.testutil.DatabindTestUtil;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotSame;

public class JsonNodeDeepCopyTest extends DatabindTestUtil
{
    private final ObjectMapper mapper = new ObjectMapper();

    @Test
    public void testWithObjectSimple()
    {
        ObjectNode root = mapper.createObjectNode();
        root.put("a", 3);
        assertEquals(1, root.size());

        ObjectNode copy = root.deepCopy();
        assertEquals(1, copy.size());

        // adding to root won't change copy:
        root.put("b", 7);
        assertEquals(2, root.size());
        assertEquals(1, copy.size());

        // nor vice versa
        copy.put("c", 3);
        assertEquals(2, root.size());
        assertEquals(2, copy.size());
    }

    @Test
    public void testWithArraySimple()
    {
        ArrayNode root = mapper.createArrayNode();
        root.add("a");
        assertEquals(1, root.size());

        ArrayNode copy = root.deepCopy();
        assertEquals(1, copy.size());

        // adding to root won't change copy:
        root.add( 7);
        assertEquals(2, root.size());
        assertEquals(1, copy.size());

        // nor vice versa
        copy.add(3);
        assertEquals(2, root.size());
        assertEquals(2, copy.size());
    }

    @Test
    public void testWithNested()
    {
        ObjectNode root = mapper.createObjectNode();
        ObjectNode leafObject = root.putObject("ob");
        ArrayNode leafArray = root.putArray("arr");
        assertEquals(2, root.size());

        leafObject.put("a", 3);
        assertEquals(1, leafObject.size());
        leafArray.add(true);
        assertEquals(1, leafArray.size());

        ObjectNode copy = root.deepCopy();
        assertNotSame(copy, root);
        assertEquals(2, copy.size());

        // should be detached, once again

        leafObject.put("x", 9);
        assertEquals(2, leafObject.size());
        assertEquals(1, copy.get("ob").size());

        leafArray.add("foobar");
        assertEquals(2, leafArray.size());
        assertEquals(1, copy.get("arr").size());

        // nor vice versa
        ((ObjectNode) copy.get("ob")).put("c", 3);
        assertEquals(2, leafObject.size());
        assertEquals(2, copy.get("ob").size());

        ((ArrayNode) copy.get("arr")).add(13);
        assertEquals(2, leafArray.size());
        assertEquals(2, copy.get("arr").size());
    }
}
